/*
 * Copyright 2007 Yegor Jbanov
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 *   
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.spicesoft.clientobjects;

import com.spicesoft.clientobjects.core.PropertyChangeListenerSupport;
import com.spicesoft.clientobjects.core.PropertyInterceptor;
import com.spicesoft.clientobjects.core.ProxyObject;

import net.sf.cglib.proxy.Enhancer;

/**
 * This class provides methods for enhancing POJO beans.
 * 
 * @author Yegor Jbanov
 *
 * @param <E> The class type that will be enhanced by this enhancer
 */
public class BeanEnhancer<E> {
  
  private Enhancer enhancer;
  private PropertyInterceptor interceptor;
  
  private BeanEnhancer(E original) {
    Class<? extends Object> clazz = original.getClass();
    if (!BeanRegistry.isRegistered(clazz)) {
      throw new IllegalArgumentException(clazz + " is not registered in the BeanRegistry");
    }
    
    this.interceptor = new PropertyInterceptor(original);
    this.enhancer = new Enhancer();
    
    this.enhancer.setSuperclass(clazz);
    this.enhancer.setInterfaces(new Class[] {PropertyChangeListenerSupport.class, ProxyObject.class});
    this.enhancer.setCallback(this.interceptor);
  }

  @SuppressWarnings("unchecked")
  public E addPropertyChangeSupport() {
    E enhanced = (E) this.enhancer.create();
    return enhanced;
  }
  
  public static <T> T addPropertyChangeSupport(T originalPojo) {
    if (originalPojo instanceof PropertyChangeListenerSupport) {
      // Already enhanced
      return originalPojo;
    }
    
    return (new BeanEnhancer<T>(originalPojo)).addPropertyChangeSupport();
  }

}
